본문으로 건너뛰기

useContext

🧑🏻‍💻 useContext


useContext 는 컴포넌트에서 context를 읽고 구독할 수 있게 해주는 React Hook이다.

✅ useContext 문법

const value = useContext(SomeContext)
  • SomeContext인 context 자체는 정보를 보유하지 않고, 상위 <Context.Provider>에서 제공하거나 읽을 수 있는 정보를 나타낸다.

  • 반환값은 createContext에 전달한 defaultValue가 된다.

  • 반환된 값은 항상 최신 값이다.

🧑🏻‍💻 알고 가기


✅ context

  • context는 prop drilling, 즉 prop를 계속해서 하위 컴포넌트로 내려주는 작업을 보완하고자 나왔다. 즉 아파트의 온수 시스템처럼 아파트라는 Provider 안에서 원하는 곳에서 쓸 수 있다는 것을 의미한다.

✅ useContext는 어떻게 동작하는가?

  • React는 context 값을 결정하기 위해 컴포넌트 트리를 검색하고, 특정 context 상위의 가장 가까운 context provider를 찾는다.

  • React는 context가 변경되면 context를 받는 provider부터 해당 context를 읽는 자식들을 전부 자동으로 리렌더링한다.

✅ useContext를 언제 사용해야 하는가?

  • 테마 설정 (다크모드)

  • 로그인 상태 구현

✅ <Context.Provider> 사용 위치

  • useContext() 호출은 항상 해당 컴포넌트 위에 있는 가장 가까운 provider에서 값을 찾으므로, 해당 <Context.Provider>useContext() 호출을 수행하는 컴포넌트의 위에 있어야 한다.

🧑🏻‍💻 활용 및 생각할 거리


✅ context 로 객체 및 함수 전달 시 리렌더링 최적화하는 방법

  • context로 전달된 객체와 함수는 렌더링 시 다른 객체와 다른 함수가 된다. 이 때문에 기초 데이터가 변경되지 않았어도 해당 context를 읽는 자식들을 전부 자동으로 리렌더링되는 문제가 발생한다.

  • 따라서 리렌더링 최적화를 위해 함수를 useCallback으로 감싸고 객체 생성은 useMemo로 감싸주어 사용하는 것이 좋다.

import { useCallback, useMemo } from 'react';

function MyApp() {
const [currentUser, setCurrentUser] = useState(null);

const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);

const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);

return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}

✅ useContext()와 useState()로 다크 모드 구현하기

  1. 부모 컴포넌트에 theme state를 선언한 후 현재 state를 context 값으로 provider에 전달한다.
  2. 하위 컴포넌트가 전달받은 theme state를 업데이트하기 위해 setTheme함수를 호출하면 해당 state를 사용하는 컴포넌트들 모두 변경된 값으로 리렌더링된다.
function MyPage() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Switch to light theme
</Button>
</ThemeContext.Provider>
);
}